#!/usr/bin/python
# -*- coding: utf-8 -*-

import logging
import os
import random
import table

import bpmf
import singer_db

SONG_LIST_FILE = 'data/songlist.txt'
FILE_ENCODING = 'utf-8'
FS_ENCODING = 'utf-8'

class SongDB:
    def __init__(self, config):
        self._config = config
        self._singer_db = singer_db.SingerDB(config)
        self._singers = {}
        self._songs = {}
        self._filenames = {}

        if 'path' in config:
            # Scan for songs in the specified directory.
            for root, dirs, files in os.walk(config['path']):
                for f in files:
                    self._AddFile(os.path.join(root, f).decode(FS_ENCODING))
        else:
            # Get song list from the file.
            for line in open(SONG_LIST_FILE, 'r'):
                path = line.decode(FILE_ENCODING).strip()
                if path:
                    self._AddFile(path)

        for key in self._singers:
            self._singers[key] = list(self._singers[key])
            self._singers[key].sort(cmp=bpmf.Cmp)

        for key in self._songs:
            self._songs[key] = list(self._songs[key])
            self._songs[key].sort(cmp=bpmf.LenCmp)

        logging.info('loaded %d songs', len(self._filenames))

    def _AddFile(self, path):
        components = table.s2t(path).split('/')
        filename = components[-1]
        singer_dir = -2 - int(self._config['singer_subdir_depth'])
        singer = components[singer_dir]

        singer_type = self._singer_db.GetSingerType(
            singer, components[0:singer_dir])

        dot = filename.rfind('.')
        if dot == -1:
            dot = len(filename)
        song = filename[0:dot].replace('&', '')

        singers = self._singers.setdefault(singer_type, set())
        singers.add(singer)

        singer_key = self._GetSingerKey(singer_type, singer)
        songs = self._songs.setdefault(singer_key, set())
        songs.add(song)

        song_key = self._GetSongKey(singer_type, singer, song)
        self._filenames[song_key] = path

    def _GetSingerKey(self, singer_type, singer):
        return os.path.join(singer_type, singer)

    def _GetSongKey(self, singer_type, singer, song):
        return os.path.join(singer_type, singer, song)

    def _ParseSongKey(self, key):
        return key.split(os.sep)

    def GetSingers(self, singer_type):
        return self._singers.get(singer_type, list())

    def GetSongs(self, singer_type, singer):
        singer_key = self._GetSingerKey(singer_type, singer)
        return self._songs.get(singer_key, list())

    def GetFilename(self, singer_type, singer, song):
        song_key = self._GetSongKey(singer_type, singer, song)
        return self._filenames.get(song_key, '')

    def GetRandom(self):
        n = int(random.uniform(0, len(self._filenames)))
        key = self._filenames.keys()[n]
        (singer_type, singer, song) = self._ParseSongKey(key)
        return (singer, song, self._filenames[key])
